"""
This script contains the mapped classes that are used by the mapper
to populate the database in SQLAlchemy
Written By: Daniel Ortiz
Date: October 23 2007
"""
import datetime
class User(object):
    """New class that maps to table users"""
    def __init__(self, username, password):
        self.username = username
        self.password = password

    def __repr__(self):
        return '<User("%s", "%s")>' % (self.username, self.password)

    def get(self):
        return [self.username, self.password]

    def oname(self):
        return 'User'


class Owner(object):
    """New class tha maps to table owner"""
    def __init__(self, name, password):
        self.name = name
        self.password = password

    def __repr__(self):
        return '<Owner("%s", "%s">' % (self.name, self.password)

    def get(self):
        return [self.name, self.password]

    def oname(self):
        return 'Owner'

class Mailbox(object):
    def __init__(self, alias, size, username, domain, password, dtime, protocol, iserver, 
                 iport, issl, oserver, oport, ossl):
        self.__Update(alias, size, username, domain, password, dtime, protocol, iserver, 
                 iport, issl, oserver, oport, ossl)
        
    def __Update(self, alias, size, username, domain, password, dtime, protocol, iserver, 
                 iport, issl, oserver, oport, ossl):
        self.alias = alias
        self.size = size
        self.username = username
        self.domain = domain
        self.password = password
        self.dtime = dtime
        self.protocol = protocol
        self.iserver = iserver
        self.iport = iport
        self.issl = issl
        self.oserver = oserver
        self.oport = oport
        self.ossl = ossl
        
        self.added = False
    
    def get(self):
        return [self.alias, self.size, self.username, self.domain, self.password, self.dtime, self.protocol,
                 self.iserver,self.iport, self.issl, self.oserver, self.oport, self.ossl]
        
    def __repr__(self):
        return 'Mailbox<%s, %s>' % (self.id, self.size)
    
    def startupTime(self, time):
        self.time = time
        
    def __eq__(self, other):
        """Test for equality between Mapclasses"""
        if isinstance(other, Mailbox):
            for k1, k2 in zip(self.get(), other.get()):
                if k1 != k2:
                    return False
            return True
        else:
            return False
        
    def __ne__(self, other):
        """Test whether two objects are not equal"""
        return not self.__eq__(other)
    
    def update(self, other):
        """Copy other into self"""
        self.__Update(*other.get())
        
    def isTime(self, time):
        if not hasattr(self, 'time'):
            self.startupTime(datetime.datetime.now())
        return self.time + datetime.timedelta(minutes = int(self.dtime)) < time
    
    def kwargs(self):
        return {'alias' : self.alias, 'size' : self.size, 'username' : self.username,
                'domain' : self.domain, 'password' : self.password, 'dtime' : self.dtime, 'protocol' : self.protocol,
                'iserver' : self.iserver, 'iport' : self.iport, 'issl' : self.issl, 'oserver': self.oserver, 
                'oport' : self.oport, 'ossl': self.ossl}
        
        

def address_string(data):
    """Generic conversion of an Address structure to a string"""
    if isinstance(data, list):
        if data[0][0]:
            return "<%s> %s@%s" % (data[0][0], data[0][2], data[0][3])
        else:
            return "%s@%s" % (data[0][2], data[0][3])
    else:
        return ""

def create_mail(flags, uid, envelope, folder, id):
    flags = ":".join(flags)
    date = envelope[0]
    subject = envelope[1]
    mfrom = address_string(envelope[2])
    sender = address_string(envelope[3])
    reply_to = address_string(envelope[4])
    mto = address_string(envelope[5])
    cc = address_string(envelope[6])
    bcc = address_string(envelope[7])
    return Mail(date, mfrom, sender, uid, flags, '', reply_to, '', mto, cc, bcc, subject, '', '', '', folder)

def create_incomplete_mail(**kw):
    def __get(str, kw):
        if kw.has_key(str):
            return kw[str]
        else:
            return ""
    from_who = __get('from_who', kw)
    subject = __get('isubject', kw)
    attachments = __get('attachments', kw)
    body = __get('body', kw)
    to = __get('ito', kw)
    cc = __get('icc', kw)
    bcc = __get('ibcc', kw)
    mailbox = __get('mailbox', kw)
    mail = __get('mail', kw)
    date = str(datetime.datetime.now())
    m = Mail(date, from_who, from_who, mail.uid, mail.flags, '',from_who, body, to, cc, bcc, subject, mail.content_type,
             mail.encoding, mail.charset, mail.folder)
    m.attachments = attachments
    return m

def create_Mail_from_email(email, mailbox, index):
    def __get(str, kw):
        if kw.has_key(str):
            return kw[str]
        else:
            return ''
    date = __get('Date', email)
    subject = __get('Subject', email)
    from_who = __get('From', email)
    to = __get('To', email)
    body = str(email)
    cc = __get('Cc', email)
    reply_to = __get('Reply-To', email)
    content_type = email.get_content_type()
    encoding = __get("Content-Transfer-Encoding", email)
    charset = email.get_content_charset()
    return Mail(date, from_who, '', index, '', '',reply_to, body, to, cc, '', subject, content_type, encoding, charset, "INBOX")

class Mail(object):
    def __init__(self, orig_date, from_who, sender, uid, flags, local_flags, reply_to, body,
                 to, cc, bcc, subject, encoding, content, charset, folder):
        self.__Update(orig_date, from_who, sender, uid, flags, local_flags, reply_to, body,
                 to, cc, bcc, subject, encoding, content, charset, folder)
        
    def __Update(self, orig_date, from_who, sender, uid, flags, local_flags, reply_to, body,
                 to, cc, bcc, subject, encoding, content, charset, folder):
        self.orig_date = orig_date
        self.from_who = from_who
        self.sender = sender
        self.uid = uid
        self.flags = flags
        self.reply_to = reply_to
        self.local_flags = local_flags
        self.body = body
        self.to = to
        self.cc = cc
        self.bcc = bcc
        self.subject = subject
        self.encoding = encoding
        self.folder = folder
        self.content_type = content
        self.charset = charset
        
        self.attachments = []
        self.alternative = False
    
    
    def kwargs(self):
        return {'orig_date' : self.orig_date, 'from_who': self.from_who,
                'sender' : self.sender, 'uid' : self.uid, 'flags' : self.flags, 'local_flags' : self.local_flags, 
                'reply_to' : self.reply_to, 'body' : self.body, 'to' : self.to, 'cc' : self.cc, 'bcc' : self.bcc, 
                'subject' : self.subject, 'content_type': self.content_type, 'encoding' : self.encoding, 
                'charset' : self.charset,'folder' : self.folder}
        
    def __eq__(self, other):
        """Test for equality between Mapclasses"""
        if isinstance(other, Mail):
            for k1, k2 in zip(self.get(), other.get()):
                if k1 != k2:
                    return False
            return True
        else:
            return False
        
    def __ne__(self, other):
        """Test whether two objects are not equal"""
        return not self.__eq__(other)
        
    def get(self):
        return [self.orig_date, self.from_who, self.sender, self.uid, self.flags, self.local_flags, self.reply_to, 
                self.body, self.to, self.cc, self.bcc, self.subject, self.encoding, self.content_type, 
                self.charset, self.folder]
        
    def update(self, other):
        """Update the values of the elements of the mail class with other"""
        self.__Update(*other.get())

    def __repr__(self):
        return "<Mail('%s, %s')>" % (self.mailbox_id, self.subject)
    

#class Mailbox(object):
#    """New class maps to table mailbox"""
#    def __init__(self, alias, private = True, size = 0):
#        self.alias = alias              # home
#        self.private = private          # Who can see my email?
#        self.size = size
#        self.first_call = False
#        self.current_folder = ''
#        
#    def __repr__(self):
#        return '<Mailbox("%s", "%s")>' % (self.alias,
#                                          str(self.private))
#
#    def get(self):
#        return [self.alias, self.private, self.size]
#    
#    def __eq__(self, other):
#        """Test for equality between Mapclasses"""
#        if isinstance(other, Mailbox):
#            for k1, k2 in zip(self.get(), other.get()):
#                if k1 != k2:
#                    return False
#            return True
#        else:
#            return False
#        
#    def __ne__(self, other):
#        """Test whether two objects are not equal"""
#        return not self.__eq__(other)
#
#    def oname(self):
#        return 'Mailbox'

class Folder(object):
    """New class which maps to the folder table"""
    def __init__(self, alias):
        self.alias = alias

    def __repr__(self):
        return '<Folder(%s)>' % self.alias

    def get(self):
        return [self.alias]

    def oname(self):
        return 'Folder'

class Attachment(object):
    """Object encapsulates an email attachment"""
    def __init__(self, title, data, size, encoding, charset = '', content_type = '', alternative = False, mixed = False):
        self.title = title
        self.data = data
        self.size = size
        self.encoding = encoding
        self.alternative = alternative
        self.content_type = content_type
        self.charset = charset
        self.mixed = mixed
        
    def __repr__(self):
        return '<Attachment("%s", "%s")>' % (self.title, self.size)

    def get(self):
        return [self.title, self.data, self.size, self.encoding,
                self.alternative, self.mixed]

    def oname(self):
        return 'Attachment'

#class Mail(object):
#    """New class maps to the RFC 2822 definition of mail. Objects that
#       can exists multiple times in an email, such as 'comments' have
#       their own objects, and are foreign keys in this table. Furthermore,
#       a control variable state defines the domain of the mail. (i.e. draft,
#       sent-mail, etc.)
#       """
#    def __init__(self, iorig_date, ifrom, ibody, state, iencoding = None, isender = None,
#                 ireply_to = None, ito = None, icc = None, ibcc = None,
#                 imessage_id = None, iin_reply_to = None, ireferences = None,
#                 isubject = None, iuid = None, iflags = None):
#
#        # Header
#        self.orig_date = iorig_date
#        self.from_who = ifrom
#        self.sender = isender
#        self.reply_to = ireply_to
#        self.to = ito
#        self.cc = icc
#        self.bcc = ibcc
#        self.message_id = imessage_id
#        self.in_reply_to = iin_reply_to
#        self.references = ireferences
#        self.subject = isubject
#        self.encoding = iencoding
#
#        # Body
#        self.body = ibody
#
#        # Control
#        self.state = state
#        self.uid = iuid
#        self.flags = iflags
#        
#        # Attachments
#        self.attachments = []
#
#    def __repr__(self):
#        return '<Mail("%s", "%s", "%s")>' % (self.orig_date, self.from_who,
#                                             self.state)
#    
#    def __eq__(self, other):
#        """Test for equality between Mapclasses"""
#        if isinstance(other, Mail):
#            for k1, k2 in zip(self.get(), other.get()):
#                if k1 != k2:
#                    return False
#            return True
#        else:
#            return False
#        
#    def __ne__(self, other):
#        """Test whether two objects are not equal"""
#        return not self.__eq__(other)
#    
#    def get(self):
#        return [self.orig_date, self.from_who, self.body, self.state, self.encoding,
#                self.sender, self.reply_to, self.to, self.cc, self.bcc,
#                self.message_id, self.in_reply_to, self.references,
#                self.subject, self.uid, self.flags]
#
#    def oname(self):
#        return 'Mail'
    
class Domain(object):
    """New class maps to domain table. The domain contains information
       to connect to the server instance of the mailbox.(i.e enabler)"""
    def __init__(self, username, domain, password, dtime,
                 protocol = 'imap4', iserver = '', iport = 0,
                 issl = True, oserver = '', oport = 0, ossl = True,
                 mail = ''):
        """ i.e ddd@google.com username = dd domain = google.com"""
        self.username = username
        self.domain = domain
        self.password = password
        self.dtime = dtime
        self.protocol = protocol
        self.iserver = iserver
        self.iport = iport
        self.issl = issl
        self.oserver = oserver
        self.oport = oport
        self.ossl = ossl
        self.mail = mail

    def __repr__(self):
        return '<Domain("%s", "%s")>' % (self.username, self.domain)

    def get(self):
        return [self.username, self.domain, self.password, self.dtime,
                self.protocol, self.iserver, self.iport, self.issl,
                self.oserver, self.oport, self.ossl, self.mail]

    def oname(self):
        return 'Domain'

class AddressBook(object):
    """New class which maps to the address book table"""
    def __init__(self, alias):
        self.alias = alias

class Address(object):
    """New class that maps to the address table"""
    def __init__(self, email, fullname):
        self.email = email
        self.fullname = fullname
#
#class AddressBook(object):
#    """New class which maps to the address book table"""
#    def __init__(self, id, alias):
#        self.id = id
#        self.alias = alias
#
#    def __repr__(self):
#        return '<AdressBook("%s")>' % self.alias
#
#    def kwargs(self):
#        return {"alias" : self.alias}
#
#    def get(self):
#        return [self.id, self.alias]
#
#    def oname(self):
#        return 'AddressBook'
#
#class Address(object):
#    """New class that maps to the address table"""
#    def __init__(self, id, abook_id, email, fullname):
#        self.id = id
#        self.abook_id = abook_id
#        self.email = email
#        self.fullname = fullname
#
#    def __repr__(self):
#        return '<Address("%s", "%s")>' % (self.email, self.fullname)
#
#    def kwargs(self):
#        return {"abook_id" : self.abook_id, "email" : self.email, "fullname" : self.fullname}
#
#    def get(self):
#        return [self.id, self.email, self.fullname]
#
#    def oname(self):
#        return 'Address'

class Control(object):
    """New class that maps the control table"""
    def __init__(self, multiple_users, sc_arch, password, lmailbox = ''):
        """
        multiple_users - will multiple people be using this Kupla instance
        sc_arch - will this instance of Kupla allow be using the server
        client architecture.
        password - is this Kupla instance password protected.
        """
        self.multiple_users = multiple_users
        self.sc_arch = sc_arch
        self.password = password
        self.lmailbox = lmailbox

    def __repr__(self):
        return '<Control ("%s", "%s", "%s")>' % (self.multiple_users,
                                                 self.sc_arch,
                                                 self.password)

    def get(self):
        return [self.multiple_users, self.sc_arch, self.password, self.lmailbox]

    def oname(self):
        return 'Control'
